package org.youyun56.gpsserver.command;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.io.FileUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.youyun56.gpsserver.command.console.ConsoleCommand;
import org.youyun56.gpsserver.command.console.Executor;
import org.youyun56.gpsserver.common.CollectionUtils;

public class CommandConfigLoader extends XMLConfigLoader {

    private static final String SERVICE_TYPE_ALL = "all";

    public CommandConfigLoader() {
        super("^(commands)(.)*(\\.)(xml)$");
    }

    public CommandConfigLoader(String pattern) {
        super(pattern);
    }

    @Override
    public void loadConfig(String file) throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(this.getFileInputStream(file));
        Element root = document.getDocumentElement();
        NodeList list = root.getElementsByTagName("command");
        Node node, child;

        for (int i = 0; i < list.getLength(); i++) {
            node = list.item(i);
            NodeList childs = node.getChildNodes();
            ConsoleCommand c = new ConsoleCommand();
            for (int t = 0; t < childs.getLength(); t++) {
                child = childs.item(t);
                if (child.getNodeType() != Node.ELEMENT_NODE) {
                    continue;
                }
                String txt = null;
                if (child.getFirstChild() != null) {
                    txt = child.getFirstChild().getNodeValue().trim();
                    txt = txt.trim();
                }
                if (child.getNodeName().equals("regular-expression")) {
                    c.setRegExp(txt);
                } else if (child.getNodeName().equals("description")) {
                    c.setDescription(txt);
                } else if (child.getNodeName().equals("style")) {
                    c.setStyle(txt);
                } else if (child.getNodeName().equals("executors")) {
                    List<Executor> executors = loadExecutors(child);
                    c.setExecutors(executors);
                } else {
                    continue;
                }
            }
            if (CollectionUtils.isNotEmpty(c.getExecutors())) {
                CommandAssigner.getInstance().registerCommand(c);
            }
        }
        root = null;
        document = null;
        builder = null;
        factory = null;
    }

    protected InputStream getFileInputStream(String filePath) throws IOException {
        return FileUtils.openInputStream(new File(filePath));
    }

    public List<Executor> loadExecutors(Node node) {
        NodeList children = node.getChildNodes();
        if (children == null || children.getLength() == 0) {
            return null;
        }

        List<Executor> executors = new ArrayList<Executor>();
        for (int i = 0; i < children.getLength(); i++) {
            Node child = children.item(i);

            if (child.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            // System.out.println(child.getNodeName());

            Executor e = parseExecutor(child);
            if (e != null) {
                executors.add(e);
            }
        }
        return executors;
    }

    private Executor parseExecutor(Node child) {
        Executor e = new Executor();
        NodeList list = child.getChildNodes();
        Node n = null;
        for (int t = 0; t < list.getLength(); t++) {
            n = list.item(t);
            if (n.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            String txt = null;
            if (n.getFirstChild() != null) {
                txt = n.getFirstChild().getNodeValue().trim();
                txt = txt.trim();
            }

            if (n.getNodeName().equals("server-type")) {
                // txt = txt.toLowerCase();
                // if (!txt.equals(SERVICE_TYPE_ALL) &&
                // !txt.contains(MainEngine.getServiceType().name().toLowerCase()))
                // {
                // return null;
                // }
            } else if (n.getNodeName().equals("action-class")) {
                e.setActionClass(txt);
            } else if (n.getNodeName().equals("method")) {
                e.setMethod(txt);
            }
        }
        return e;
    }
}